from textual.widgets import Static, LoadingIndicator
from textual.reactive import reactive
from textual.containers import Horizontal, Vertical

import psutil

from typing import Dict
length = 31
height = 8
interval = 1.5
cpu_percent = 0.00


class CpuBar(Static):
    length = length
    height = height
    data = []  # 存储cpu_percent原始数据
    graphics = []  # 字符串图像
    
    graph: Dict[tuple, str] = {
        (0,0) : " ", (0,1) : "⢀", (0,2) : "⢠", (0,3) : "⢰", (0,4) : "⢸",
        (1,0) : "⡀", (1,1) : "⣀", (1,2) : "⣠", (1,3) : "⣰", (1,4) : "⣸",
        (2,0) : "⡄", (2,1) : "⣄", (2,2) : "⣤", (2,3) : "⣴", (2,4) : "⣼",
        (3,0) : "⡆", (3,1) : "⣆", (3,2) : "⣦", (3,3) : "⣶", (3,4) : "⣾",
        (4,0) : "⡇", (4,1) : "⣇", (4,2) : "⣧", (4,3) : "⣷", (4,4) : "⣿"
	}
    cpu_per_init = round(psutil.cpu_percent(), 2)
    cpu_per = round(cpu_per_init*0.28)+1
    count = reactive(1)
    interval = interval  # 刷新间隔

    def on_mount(self):
        self.update_cpu_timer=self.set_interval(self.interval, self.update_cpu_per, pause=False)


    def update_cpu_per(self):
        self.count+=1
        self.cpu_per_init = round(psutil.cpu_percent(), 2)
        self.cpu_per = round(self.cpu_per_init*0.28)+1
        

    def watch_cpu_per(self):
        self.validate_count(self.count)
        

    def validate_count(self, count: int):
        """处理可视化图像的绘制及相关数据的处理"""
        final_graphic = ""
        full_datas=[]  # 存储处理后的数据: list[tuple(x3,x2), tuple(x1,0)]
        self.graphics = []
        for i in range(self.height):  # height = 8
            it = []
            for j in range(int(self.length/2)):  # length = 31
                it.append(' ')
            if i != self.height-1:  # 8-1=7
                it.append('\n')
            self.graphics.append(it)

        if count > self.length:
            self.data.pop(-1)

        self.data.insert(0, self.cpu_per)  # 头部插入

        if len(self.data) % 2 != 0:  # 为奇数
            finall_data = (self.data[-1], 0)  # tuple(left, right)
            if len(self.data)-1 != 0:  # eg.[x3.x2, x1.0]
                for i in range(0, len(self.data)-1, 2):  # 2个一组存储
                    full_datas.append((self.data[i], self.data[i+1]))  # tuple(left, right)
            full_datas.append(finall_data)
        else:
            for i in range(0, len(self.data), 2):  # 2个一组存储
                full_datas.append((self.data[i], self.data[i+1]))  # tuple(left, right)

        # 处理数据的绘制
        # full_datas: list[tuple(x3,x2), tuple(x1,0)]
        for j in range(len(full_datas)):
            left = full_datas[j][0]
            right = full_datas[j][1]
            item = []  # graph_index存储的元素
            while (left//4 > 0) or (right//4 > 0):
                if (left//4==0) and (right//4 > 0):
                    item.append((left, 4))
                    right=right-4
                    left = left - left
                elif (right//4==0) and (left//4 > 0):
                    item.append((4, right))
                    left=left-4
                    right = right- right
                else:
                    item.append((4,4))
                    left=left-4
                    right=right-4
            if (left//4==0) and (right//4==0) :
                item.append((left, right))

            index = 0
            for i in range(len(self.graphics)-1, len(self.graphics)-1-len(item), -1):
                self.graphics[i][j] = self.graph[item[index]]
                index += 1

        for k in range(len(self.graphics)):
            s = ''
            final_graphic += s.join(self.graphics[k])

        self.update(final_graphic)
        return count
    

class MemBar(Static):
    length = length
    height = height
    data = []  # 存储mem_per原始数据
    graphics = []  # 字符串图像
    
    graph: Dict[tuple, str] = {
        (0,0) : " ", (0,1) : "⢀", (0,2) : "⢠", (0,3) : "⢰", (0,4) : "⢸",
        (1,0) : "⡀", (1,1) : "⣀", (1,2) : "⣠", (1,3) : "⣰", (1,4) : "⣸",
        (2,0) : "⡄", (2,1) : "⣄", (2,2) : "⣤", (2,3) : "⣴", (2,4) : "⣼",
        (3,0) : "⡆", (3,1) : "⣆", (3,2) : "⣦", (3,3) : "⣶", (3,4) : "⣾",
        (4,0) : "⡇", (4,1) : "⣇", (4,2) : "⣧", (4,3) : "⣷", (4,4) : "⣿"
	}
    mem_per_init = psutil.virtual_memory().percent
    mem_per = round(mem_per_init*0.28)+1
    count = reactive(1)
    interval = interval  # 刷新间隔

    total_mem = psutil.virtual_memory()[0]
    unit = 'B'

    def on_mount(self):
        self.update_mem_timer = self.set_interval(self.interval, self.update_mem_per, pause=False)
        
    def update_mem_per(self):
        self.count+=1
        self.mem_per_init = round(psutil.virtual_memory().percent, 1)
        self.mem_per = round(self.mem_per_init*0.28)+1
    
    def watch_mem_per(self):
        self.validate_count(self.count)

    def validate_count(self, count: int):
        final_graphic = ""
        full_datas=[]  # 存储处理后的数据: list[tuple(x3,x2), tuple(x1,0)]
        self.graphics = []
        for i in range(self.height):
            it = []
            for j in range(int(self.length/2)):
                it.append(' ')
            if i != self.height-1:
                it.append('\n')
            self.graphics.append(it)

        if count > self.length:
            self.data.pop(-1)

        self.data.insert(0, self.mem_per)  # 头部插入

        if len(self.data) % 2 != 0:  # 为奇数
            finall_data = (self.data[-1], 0)  # tuple(left, right)
            if len(self.data)-1 != 0:  # eg.[x3.x2, x1.0]
                for i in range(0, len(self.data)-1, 2):  # 2个一组存储
                    full_datas.append((self.data[i], self.data[i+1]))  # tuple(left, right)
            full_datas.append(finall_data)
        else:
            for i in range(0, len(self.data), 2):  # 2个一组存储
                full_datas.append((self.data[i], self.data[i+1]))  # tuple(left, right)

        # 处理数据的绘制
        # full_datas: list[tuple(x3,x2), tuple(x1,0)]
        for j in range(len(full_datas)):
            left = full_datas[j][0]
            right = full_datas[j][1]
            item = []  # graph_index存储的元素
            while (left//4 > 0) or (right//4 > 0):
                # print(left, right)
                if (left//4==0) and (right//4 > 0):
                    item.append((left, 4))
                    right=right-4
                    left = left - left
                elif (right//4==0) and (left//4 > 0):
                    item.append((4, right))
                    left=left-4
                    right = right- right
                else:
                    item.append((4,4))
                    left=left-4
                    right=right-4
            if (left//4==0) and (right//4==0) :
                item.append((left, right))

            index = 0
            for i in range(len(self.graphics)-1, len(self.graphics)-1-len(item), -1):
                self.graphics[i][j] = self.graph[item[index]]
                index += 1

        for k in range(len(self.graphics)):
            s = ''
            final_graphic += s.join(self.graphics[k])
        self.update(final_graphic)
        return count


class CpuBox(Static):
    interval = interval

    def __init__(self):
        super().__init__()
        self.cpubar = CpuBar(id="cpubar")
        self.membar = MemBar(id="membar")

    def on_mount(self):
        self.update_timer = self.set_interval(self.interval, self.update_datas, pause=False)
        # 内存大小以适宜单位显示
        a = self.membar.total_mem/1024
        b = a/1024
        c = b/1024
        if round(c) != 0:
            self.membar.total_mem = round(c, 2)
            self.membar.unit = 'GB'
        elif round(b) != 0:
            self.membar.total_mem = round(b, 2)
            self.membar.unit = 'MB'
        elif round(a) != 0:
            self.membar.total_mem = round(a, 2)
            self.membar.unit = 'KB'
        self.query_one("#mem_total").update(f" -> 总共: [cyan]{self.membar.total_mem}[/cyan] {self.membar.unit} ")

    def update_datas(self):
        # if self.cpubar.cpu_per_init>=0:
        self.query_one("#cpu_usage").update(f" -> 使用率: [green]{self.cpubar.cpu_per_init:>05.2f}[/green]% ")
        self.query_one("#memory_usage").update(f" -> 已使用: [green]{self.membar.mem_per_init:>05.2f}[/green]% ")
        if self.app.query(LoadingIndicator):
            self.app.query_one(LoadingIndicator).remove()

    def compose(self):
        yield Vertical(
                Horizontal(
                    Vertical(Static(f" 内存:"),
                        Static(f" -> 总共: [cyan]{self.membar.total_mem}[/cyan] {self.membar.unit} ",id="mem_total"),
                        Static(f" -> 已使用: [green]{self.membar.mem_per_init:>05.2f}[/green]% ", id="memory_usage"),
                        self.membar,
                        id="MemoryInfo",
                    ), 
                    Vertical(Static(f" Cpu:\n -> 核心数: [cyan]{psutil.cpu_count()}[/cyan] "),
                        Static(f" -> 使用率: [green]{self.cpubar.cpu_per_init:>05.2f}[/green]% ", id="cpu_usage"),
                        self.cpubar,
                        id="CpuInfo",
                    ), 
                id="cpubox_container"
                ),
            id="cpubox",
            )